
# 从 qtpy 库导入 QtWidgets 和 QtCore 模块，用于创建 GUI 界面和处理核心功能
from qtpy import QtWidgets, QtCore
import sys
# 从 collections 模块导入 OrderedDict 类，用于创建有序字典
import collections


class EditPropertiesTreeWidget(QtWidgets.QTreeWidget):
    """
    EditPropertiesTreeWidget 类继承自 QtWidgets.QTreeWidget，用于创建一个可编辑属性的树状控件。
    该控件支持拖拽操作，可添加文件夹和普通项，并能将树状模型转换为字典。
    """
    def __init__(self):
        """
        初始化 EditPropertiesTreeWidget 实例。
        调用父类的构造函数，并设置拖拽模式和隐藏表头。
        """
        # 调用父类 QtWidgets.QTreeWidget 的构造函数
        super(EditPropertiesTreeWidget, self).__init__()
        # 设置拖拽模式为内部移动，允许在控件内部拖拽项
        self.setDragDropMode(QtWidgets.QAbstractItemView.InternalMove)
        # 隐藏树状控件的表头
        self.setHeaderHidden(True)

    def addFolder(self, name, parent=None):
        """
        在树状控件中添加一个文件夹项。

        :param name: 文件夹的名称
        :param parent: 父项，若为 None 则添加为顶层项，默认为 None
        :return: 添加的文件夹项
        """
        # 获取系统样式中的文件夹图标
        icon = self.style().standardIcon(QtWidgets.QStyle.SP_DirIcon)
        # 创建一个树状控件项，显示指定名称
        item = QtWidgets.QTreeWidgetItem([name])
        # 为该项设置文件夹图标
        item.setIcon(0, icon)
        # 标记该项为文件夹
        item.isFolder = True
        if parent is None:
            # 若没有指定父项，则将该项添加为顶层项
            self.addTopLevelItem(item)
        else:
            # 若指定了父项，则将该项添加为父项的子项
            parent.addChild(item)
        return item

    def addNormal(self, name, parent=None):
        """
        在树状控件中添加一个普通项。

        :param name: 普通项的名称
        :param parent: 父项，若为 None 则添加为顶层项，默认为 None
        :return: 添加的普通项
        """
        # 创建一个树状控件项，显示指定名称
        item = QtWidgets.QTreeWidgetItem([name])
        # 清除该项的可拖放标志，使其不能作为拖放目标
        item.setFlags(item.flags() & ~QtCore.Qt.ItemIsDropEnabled)
        # 标记该项不是文件夹
        item.isFolder = False
        if parent is not None:
            # 若指定了父项，则将该项添加为父项的子项
            parent.addChild(item)
        else:
            # 若没有指定父项，则将该项添加为顶层项
            self.addTopLevelItem(item)
        return item

    def fill_dict_from_model(self, parent_index, d, model):
        """
        递归地将树状模型中的数据填充到有序字典中。

        :param parent_index: 父项的索引
        :param d: 用于存储数据的有序字典
        :param model: 树状控件的模型
        """
        # 创建一个新的有序字典，用于存储当前父项的子项数据
        v = collections.OrderedDict()
        # 遍历当前父项的所有子项
        for i in range(model.rowCount(parent_index)):
            # 获取子项的索引
            ix = model.index(i, 0, parent_index)
            # 递归调用 fill_dict_from_model 方法，填充子项数据
            self.fill_dict_from_model(ix, v, model)
        if len(v) == 0:
            # 若当前父项没有子项，则将值设为 None
            v = None
        # 将当前父项的数据和其子项数据存储到字典中
        d[parent_index.data()] = v

    def model_to_dict(self):
        """
        将树状控件的模型转换为有序字典。

        :return: 包含树状控件数据的有序字典
        """
        # 获取树状控件的模型
        model = self.model()
        # 创建一个新的有序字典，用于存储模型数据
        d = collections.OrderedDict()
        # 遍历树状控件的顶层项
        for i in range(model.rowCount()):
            # 获取顶层项的索引
            ix = model.index(i, 0)
            # 调用 fill_dict_from_model 方法，填充顶层项及其子项的数据
            self.fill_dict_from_model(ix, d, model)
        return d


if __name__ == "__main__":
    # 创建一个 Qt 应用程序实例
    app = QtWidgets.QApplication(sys.argv)
    # 创建 EditPropertiesTreeWidget 实例
    form = EditPropertiesTreeWidget()
    # 添加一个普通项
    form.addNormal("Normal")
    # 添加另一个普通项
    form.addNormal("Normal1")
    # 添加一个文件夹项
    form.addFolder("Folder")
    # 添加另一个文件夹项
    form.addFolder("Folder1")
    # 显示树状控件
    form.show()

    # 进入应用程序的事件循环
    app.exec_()